/****************************************************************************

 Copyright (C) 2009 Jean Pierre Charalambos. All rights reserved.

 Jean Pierre Charalambos (http://dis.unal.edu.co/profesores/pierre/) is an
 Affiliate Associate Professor of the Faculty of Engineering at National
 University of Colombia (http://www.unal.edu.co/).

 This file is part of maku version 0.1.

 http://code.google.com/p/maku/
 email: jpcharalambosh@unal.edu.co

 This file may be used under the terms of the GNU General Public License 
 versions 2.0 or 3.0 as published by the Free Software Foundation and
 appearing in the COPYING file included in the packaging of this file.

 This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

*****************************************************************************/

#ifndef SCENEBASE_H
#define SCENEBASE_H

/** Need TESTING under Mac and Windows.
#ifdef Q_OS_LINUX
*/
 #include "config.h"
/** Need TESTING under Mac and Windows.
#endif
*/

#ifdef WITH_GLEW
 #include <GL/glew.h>
#endif

#include <QObject>
#include <QtOpenGL>
#include <QColor>

class QAction;
class QActionGroup;
class QMenu;

using namespace Qt;

// The Scene class must be derived from QObject in order to allow a
// signal slot mechanism.

class SceneBase : public QObject {
  Q_OBJECT

public :
  enum DrawMode { StripArrays = 0, ColoredStrips, Points, Wired, HiddenLine, SolidFlat, SolidSmooth, ColoredVertices, SolidColoredFaces, SmoothColoredFaces };

  #ifdef WITH_GLEW
   SceneBase() : hasOpenGL2(0), drawBB(false), drawBS(false), p(0) {pointColor = QColor(Qt::white); createActions();}
  #else
   SceneBase() : hasOpenGL2(0), drawBB(false), drawBS(false) {pointColor = QColor(Qt::white); createActions();}
  #endif

  void setDefaultMaterial(void) const;
  
  bool hasOpenGL2, drawBB, drawBS;

  //actions and menus are public so that mainwindow can access them
  QMenu *menu;
  QAction *pointColorDialogAct;
  QAction *openTexAct;
  QAction *detachTexAct;
  QAction *decimateAct;
  //drawing Actions
  QActionGroup *drawModesActs;
  QAction *stripArraysAct;
  QAction *coloredStripsAct;
  QAction *pointsAct;
  QAction *wiredAct;
  QAction *hiddenLineAct;
  QAction *solidFlatAct;
  QAction *solidSmoothAct;
  QAction *coloredVerticesAct;
  QAction *solidColoredFacesAct;
  QAction *smoothColoredFacesAct;
  //drawing bounding objects actions
  QActionGroup *boundingGroupActs;
  QAction *boundingBoxAct;
  QAction *boundingSphereAct;

public slots:
  virtual void draw() const;
  virtual void setDrawMode(DrawMode dM) { drawMode = dM; emit changed();}
  virtual void points(bool enabled) = 0;
  #ifdef WITH_GLEW
   virtual void setShader(const QString &) const;
  #endif  
  virtual void vertexColors();
  virtual void drawBoundingBox(bool toggled) {drawBB=toggled; emit changed();}
  virtual void drawBoundingSphere(bool toggled) {drawBS=toggled; emit changed();}
  /**
  //en el caso de definir un color para la escena, debe proceder más o menos así:
  void myMaterialMethod() {
    glEnable(GL_COLOR_MATERIAL);
    sceneColor = color;
    emit changed();
  }
  */

protected slots:
  virtual void drawMesh() const = 0;
  //texture:
  void textureHandling();
  //Decimater:
  virtual bool simplifyModel() = 0;
  //drawing methods:
  virtual void currentAction(QAction *);

signals:
  void changed() const; //draw mode has changed
  void sceneChanged() const; //scene has changed
  void contentsChanged() const; //scene contents has changed
  void sceneReset() const; //scene has been reset: draws default spiral

protected:
  DrawMode drawMode;
  //texture
  virtual bool openTexture( const QString &) = 0;
  virtual void detachTexture() = 0;
  //color a emplear cuando se dibujen los vértices y el modelo no tenga definidos los colores de los mismos
  QColor pointColor;

private:
  void createActions();
  //shaders:
  #ifdef WITH_GLEW
   mutable GLuint v,f,p;
   mutable char *vs, *fs;
   QString readShaderCode(const QString &) const;
  #endif  
};

#endif
